#include "xvideothread.h"
#include "xfilter.h"

//一号视频源
static cv::VideoCapture cap1;
//二号视频源（视频融合时）
static cv::VideoCapture cap2;
 //保存视频
static cv::VideoWriter vw;

XVideoThread::XVideoThread(QObject *parent)
    : QThread{parent}
{

}

XVideoThread::~XVideoThread()
{

}

//打开一号视频源文件
bool XVideoThread::open(const string filePath)
{
    seek(0); //一打开就seek
    mutex.lock();
    bool re = cap1.open(filePath);
    mutex.unlock();
    if (!re) {
        return re;
    }
    //获取视频宽高
    width = cap1.get(cv::CAP_PROP_FRAME_WIDTH);
    height = cap1.get(cv::CAP_PROP_FRAME_HEIGHT);
    //获取fps
    fps = cap1.get(cv::CAP_PROP_FPS);
    if (fps <= 0) {
        fps = 25;
    }
    src1File = filePath; //原视频路径
    double count = cap1.get(cv::CAP_PROP_FRAME_COUNT); //总帧数
    totalMs = (count / (double)fps) * 1000;  //总时长（ms)
    return true;
}

bool XVideoThread::open2(const string filePath)
{
    seek(0); //一打开就seek
    mutex.lock();
    bool re = cap2.open(filePath);
    mutex.unlock();
    if (!re) {
        return re;
    }
    //获取视频2宽高
    width2 = cap2.get(cv::CAP_PROP_FRAME_WIDTH);
    height2 = cap2.get(cv::CAP_PROP_FRAME_HEIGHT);
    return true;
}

void XVideoThread::run()
{
    cv::Mat mat1;
    for (;;) {
        mutex.lock();
        if (isExit) {
            mutex.unlock();//析构的时候退出
            break;
        }
        //判断视频是否打开
        if (!cap1.isOpened()) {
            mutex.unlock();
            msleep(5);
            continue;
        }
        if (!isPlay) { //暂停状态
            mutex.unlock();
            msleep(5);
            continue;
        }
        //读取一帧视频，解码，颜色转换
        int cur = cap1.get(cv::CAP_PROP_POS_FRAMES); //获取当前帧数
        if ((endPos > 0 && cur >= endPos) || !cap1.read(mat1) || mat1.empty()) {
            mutex.unlock();
            //导出在结尾位置，停止导出
            if(isWrite) {   //正在导出视频
                stopSave();
                emit sigSaveEnd();
            }
            msleep(5);
            continue;
        }
        cv::Mat mat2 = mark;
        //视频融合
        if (cap2.isOpened()) {
            cap2.read(mat2);
        }
        //非导出状态下，显示原图像
        if (!isWrite) {
            emit sigViewImage1(mat1);
            if (!mat2.empty()) {
                emit sigViewImage2(mat2);
            }
        }
        //通过过滤器处理
        cv::Mat des = XFilter::getInstance()->fFilter(mat1, mat2);
        //非导出状态下，显示生成后图像
        if (!isWrite) {
            emit sigViewDes(des);
        }
        int s = 0;
        s = 850 / fps; //根据fps设置视频播放速度
        if (isWrite) { //导出视频时，不需要fps
            s = 1;
            vw.write(des);
        }
        msleep(s);
        mutex.unlock();
    }
}

//返回当前播放位置
double XVideoThread::getPos()
{
    double pos = 0;
    mutex.lock();
    if (!cap1.isOpened()) {
        mutex.unlock();
        return pos;
    }
    double count = cap1.get(cv::CAP_PROP_FRAME_COUNT); //获取总大小
    double cur = cap1.get(cv::CAP_PROP_POS_FRAMES); //获取当前播放位置
    if (count > 0.001) {
        pos = cur / count; //算滑动条位置
    }
    mutex.unlock();
    return pos;
}

bool XVideoThread::seek(int frame)
{
    mutex.lock();
    if (!cap1.isOpened()) {
        mutex.unlock();
        return false;
    }
    int re = cap1.set(cv::CAP_PROP_POS_FRAMES, frame);
    if (cap2.isOpened()) {
        cap2.set(cv::CAP_PROP_POS_FRAMES, frame);
    }
    mutex.unlock();
    return re;
}

bool XVideoThread::seek(double pos)
{
    double count = cap1.get(cv::CAP_PROP_FRAME_COUNT); //获取总大小
    int frame = pos * count;
    return seek(frame);
}

bool XVideoThread::startSave(const string filePath, int width, int height, bool isColor)
{
    seek(beginPos);
    mutex.lock();
    if (!cap1.isOpened()) {
        mutex.unlock();
        return false;
    }
    if (width <= 0) {
        width = cap1.get(cv::CAP_PROP_FRAME_WIDTH);
    }
    if (height <= 0) {
        height = cap1.get(cv::CAP_PROP_FRAME_HEIGHT);
    }
    vw.open(filePath, cv::VideoWriter::fourcc('m','p','4','v'), //.mp4
            this->fps,
            cv::Size(width, height),isColor
            );
    if (!vw.isOpened()) {
        mutex.unlock();
        cout << "startSave failed" << endl;
        return false;
    }
    this->isWrite = true;
    desFile = filePath;  //获取输出文件路径
    mutex.unlock();
    return true;
}

void XVideoThread::stopSave()
{
    mutex.lock();
    vw.release();
    isWrite = false;
    mutex.unlock();
}

void XVideoThread::play()
{
    mutex.lock();
    isPlay = true;
    mutex.unlock();
}

void XVideoThread::pause()
{
    mutex.lock();
    isPlay = false;
    mutex.unlock();
}

void XVideoThread::setMark(cv::Mat mark)
{
    mutex.lock();
    this->mark = mark;
    mutex.unlock();
}

void XVideoThread::setBegin(double pos)
{
    mutex.lock();
    double count = cap1.get(cv::CAP_PROP_FRAME_COUNT); //获取总大小
    int frame = pos * count;
    beginPos = frame;
    mutex.unlock();
}

void XVideoThread::setEnd(double pos)
{
    mutex.lock();
    double count = cap1.get(cv::CAP_PROP_FRAME_COUNT); //获取总大小
    int frame = pos * count;
    endPos = frame;
    mutex.unlock();
}

